﻿using YNTK.Common.Const;
using YNTK.Common.Enum;
using YNTK.Common.Filter;
using YNTK.Common.Util;
using YNTK.Dependency;
using YNTK.DynamicApiController;
using YNTK.FriendlyException;
using YNTK.JsonSerialization;
using YNTK.System.Entitys.Dto.Permission.Organize;
using YNTK.System.Entitys.Permission;
using YNTK.System.Interfaces.Permission;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System;
using Shipeng.Util;
using YNTK.DataEncryption;
using System.ComponentModel.DataAnnotations;
using YNTK.Data.MongoDB.Repositorie;
using Newtonsoft.Json;
using System.Linq.Expressions;
using LinqKit;
using YNTK.System.Interfaces.Resources;
using Microsoft.AspNetCore.Authorization;
using Yitter.IdGenerator;
using MongoDB.Driver;
using YNTK.System.Entitys.Dto.Common;
using YNTK.Common.Configuration;
using System.IO;
using YNTK.Mapster;

namespace YNTK.System.Service.Permission
{
    /// <summary>
    /// 组织管理
    /// 版 本：V1.0.0.0
    /// 版 权：云南通科科技有限公司（https://www.yntkkj.com）
    /// 作 者：李仕鹏
    /// 日 期：2021.06.07 
    /// </summary>
    [ApiDescriptionSettings(Tag = "组织管理", Name = "Organize", Order = 798)]
    [Route("api/[controller]")]
    public class OrganizeService : IOrganizeService, IDynamicApiController, ITransient
    {
        private readonly IMongoDBRepository<OrganizeMongodbEntity> _mongoDBRepository;//组组信息mongodb仓储
        private readonly ISqlSugarRepository<OrganizeEntity> _organizeRepository;//组织信息仓储
        private readonly ISqlSugarRepository<OrganizeOpenRecordEntity> _organizeOpenRepository;//组织服务仓储
        private readonly ISqlSugarRepository<UserEntity> _userRepository;
        private readonly IMongoDBRepository<MechanismEntity> _mechanismMongoDbRepository;//机构mongodb仓储
        private readonly ISqlSugarRepository<OrganizeFileEntity> _organizeFilerepository;//组织文件存储
        private readonly IMongoDBRepository<OrganizeFileEntity> _organizeFileMongoDBRepository;//组组文件mongodb仓储
        private readonly ISqlSugarRepository<OrganizeDataEntity> _dataRepository;//组织资料仓储
        private readonly IMongoDBRepository<OrganizeDataEntity> _dataMongoDbRepository;//组织资料mongodb仓储
        private readonly ISqlSugarRepository<OrganizeDataFilesEntity> _dataFilesRepository;//组织资料相关附件仓储
        private readonly IMongoDBRepository<OrganizeDataFilesEntity> _dataFilesMongoDbRepository;//组织资料相关附件mongodb仓储
        private readonly ISqlSugarRepository<OrientationFilesEntity> _orientationFilesRepository;//定置定位文件仓储
        private readonly IMongoDBRepository<OrientationFilesEntity> _orientationFilesMongoDbRepository;//定置定位文件mongodb仓储

        private readonly string _collectionName= "base_organizations";//mongodb中组织信息数据集名称
        private readonly string _orgFiles = "base_organizefiles";//mongodb中组织文件数据集名称
        private readonly string _data = "base_organizedata";//mongodb中组织资料数据集名称
        private readonly string _dataFiles = "base_organizedatafiles";//mongodb中组织资料相关附件数据集名称
        private readonly string _orientationFiles = "base_orientationfiles";//mongodb中定置定位文件数据集名称

        private readonly IDictionaryService _dictionaryService;//字典服务
        private readonly HttpContext _httpContext;
        private readonly string _mechanisms = "base_mechanisms";//mongodb中机构数据集名称

        /// <summary>
        /// 构造函数依赖注入
        /// </summary>
        public OrganizeService(IMongoDBRepository<OrganizeMongodbEntity> mongoDBRepository,
            ISqlSugarRepository<OrganizeEntity> organizeRepository,
            ISqlSugarRepository<OrganizeOpenRecordEntity> organizeOpenRepository,
            ISqlSugarRepository<UserEntity> userRepository, 
            ISqlSugarRepository<OrganizeFileEntity> organizeFilerepository,
            IMongoDBRepository<OrganizeFileEntity> organizeFileMongoDBRepository,
            IDictionaryService dictionaryService,
            IMongoDBRepository<MechanismEntity> mechanismMongoDbRepository,
            ISqlSugarRepository<OrganizeDataEntity> dataRepository,
            IMongoDBRepository<OrganizeDataEntity> dataMongoDbRepository,
            ISqlSugarRepository<OrganizeDataFilesEntity> dataFilesRepository,
            IMongoDBRepository<OrganizeDataFilesEntity> dataFilesMongoDbRepository,
            ISqlSugarRepository<OrientationFilesEntity> orientationFilesRepository,
            IMongoDBRepository<OrientationFilesEntity> orientationFilesMongoDbRepository)
        {
            _mongoDBRepository = mongoDBRepository;
            _organizeRepository = organizeRepository;
            _organizeOpenRepository = organizeOpenRepository;
            _userRepository = userRepository;
            _organizeFilerepository = organizeFilerepository;
            _organizeFileMongoDBRepository = organizeFileMongoDBRepository;
            _dictionaryService = dictionaryService;
            _mechanismMongoDbRepository = mechanismMongoDbRepository;
            _dataRepository = dataRepository;
            _dataMongoDbRepository = dataMongoDbRepository;
            _dataFilesRepository = dataFilesRepository;
            _dataFilesMongoDbRepository = dataFilesMongoDbRepository;
            _orientationFilesRepository = orientationFilesRepository;
            _orientationFilesMongoDbRepository = orientationFilesMongoDbRepository;
            _httpContext = App.HttpContext;
        }

        #region 平台运营端组织管理相关api接口
        /// <summary>
        /// 分页获取组织列表列数
        /// </summary>
        /// <param name="query">分页查询组织数据请求模型</param>
        /// <returns></returns>
        [HttpPost("platform/gets")]
        public async Task<TkPageResult<OrganizeListDto>> 
            GetList([FromBody] QueryOrganizeFilterRequestModel query)
        {
            try
            {
                var data = await _organizeRepository.Entities
                 .WhereIF(!string.IsNullOrEmpty(query.keyword),
                 it => it.FullName.Contains(query.keyword) ||
                 it.OrganizeName.Contains(query.keyword) ||
                 it.EnCode.Contains(query.keyword))
                 .WhereIF(!string.IsNullOrWhiteSpace(query.area), it => it.AdministrativeArea.Contains(query.area))
                 .WhereIF(query.state != null, it => it.State == query.state.GetHashCode())
                 .WhereIF(query.enabledMark != null, it => it.EnabledMark == query.enabledMark)
                 .Where(it => it.DeleteMark == null)
                 .OrderBy(x => x.CreatorTime, OrderByType.Desc)
                 .ToPagedListAsync(query.currentPage, query.pageSize);

                var pageList = new SqlSugarPagedList<OrganizeListDto>()
                {
                    list = data.list.Adapt<List<OrganizeListDto>>(),
                    pagination = data.pagination
                };
                if(pageList.list!=null && pageList.list.Count() > 0)
                {
                    foreach(var item in pageList.list)
                    {
                        item.stateText= EnumHelper.GetEnumDescriptionString(item.state, typeof(OrganizeStateEnum));
                    }
                }
                return TkPageResult<OrganizeListDto>.Success(pageList);
            }
            catch (Exception)
            {
                throw YNTKException.Oh("分页获取组织列表列数发生异常");
            }
        }

        /// <summary>
        /// 分页获取组织服务记录数据
        /// </summary>
        /// <param name="query">分页查询组织服务记录数据请求模型</param>
        /// <returns></returns>
        [HttpPost("platform/record")]
        public async Task<TkPageResult<OrganizeOpenRecordListDto>> 
            GetRecordList([FromBody] QueryOrganizeOpenRecordFilterRequestModel query)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh(ErrorCode.D1016);
                var data = await _organizeOpenRepository.Entities
                    .WhereIF(query.serviceType!=null,it=>it.ServiceType==query.serviceType.GetHashCode())
                    .Where(it=>it.OrganizeId==query.id && it.DeleteMark==null)
                    .OrderBy(x => x.CreatorTime, OrderByType.Desc)
                    .ToPagedListAsync(query.currentPage, query.pageSize);
                var pageList = new SqlSugarPagedList<OrganizeOpenRecordListDto>()
                {
                    list = data.list.Adapt<List<OrganizeOpenRecordListDto>>(),
                    pagination = data.pagination
                };
                if (pageList.list != null && pageList.list.Count() > 0)
                {
                    foreach (var item in pageList.list)
                    {
                        item.serviceTypeText =
                            EnumHelper.GetEnumDescriptionString(item.serviceType, typeof(OrganizeServiceTypeEnum));
                    }
                }
                return TkPageResult<OrganizeOpenRecordListDto>.Success(pageList);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"分页获取组织服务记录数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 新增组织信息
        /// </summary>
        /// <param name="input">新增组织信息请求模型</param>
        /// <returns></returns>
        [HttpPost("platform/create")]
        public async Task Create([FromBody] AddOrganizeRequestModel input)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            if (authenticationType != "0" && authenticationType != "1")
                throw YNTKException.Oh("暂无新增组织权限");
            if (await _organizeRepository.AnyAsync(o => o.EnCode == input.enCode && o.DeleteMark == null))
                throw YNTKException.Oh(ErrorCode.D2008);
            if (await _organizeRepository.AnyAsync(o => o.FullName == input.fullName && o.DeleteMark == null))
                throw YNTKException.Oh(ErrorCode.D2009);
            if (await _organizeRepository.AnyAsync(o => o.OrganizeName == input.organizeName && o.DeleteMark == null))
                throw YNTKException.Oh(ErrorCode.D2020);
            var entity = input.Adapt<OrganizeEntity>();
            entity.State = 0;//状态(0.未开通 1.已开通 2.服务到期)
            var isOk = await _organizeRepository.Context.Insertable(entity)
                .CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
            _ = isOk ?? throw YNTKException.Oh(ErrorCode.D2013);
        }

        /// <summary>
        /// 更新组织信息
        /// </summary>
        /// <param name="input">修改组织信息请求模型</param>
        /// <returns></returns>
        [HttpPut("platform/update")]
        public async Task Update([FromBody] UpdateOrganizeRequestModel input)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            if (authenticationType != "0" && authenticationType != "1")
                throw YNTKException.Oh("暂无修改组织权限");
            if (!await _organizeRepository.AnyAsync(o => o.Id == input.id && o.DeleteMark == null))
                throw YNTKException.Oh(ErrorCode.D2002);
            if (await _organizeRepository.AnyAsync(o => o.EnCode == input.enCode && o.Id != input.id && o.DeleteMark == null))
                throw YNTKException.Oh(ErrorCode.D2008);
            if (await _organizeRepository.AnyAsync(o => o.FullName == input.fullName && o.Id != input.id && o.DeleteMark == null))
                throw YNTKException.Oh(ErrorCode.D2009);
            if (await _organizeRepository.AnyAsync(o => o.OrganizeName == input.organizeName && o.Id != input.id && o.DeleteMark == null))
                throw YNTKException.Oh(ErrorCode.D2020);
            var entity = input.Adapt<OrganizeEntity>();
            var isOK = await _organizeRepository.Context.Updateable(entity)
                .IgnoreColumns(ignoreAllNullColumns: true)
                .CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync();
            if (!(isOK > 0))
                throw YNTKException.Oh(ErrorCode.D2010);
        }

        /// <summary>
        /// 删除组织,非必要请不要使用
        /// </summary>
        /// <param name="id">组织id</param>
        /// <returns></returns>
        [HttpDelete("platform/delete")]
        public async Task Delete([Required] string id)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            if (authenticationType != "0" && authenticationType != "1")
                throw YNTKException.Oh(ErrorCode.D2026);
            //删除组织信息
            var entity = await _organizeRepository.SingleAsync(o => o.Id == id && o.DeleteMark == null);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.D2002);
            var isOk = await _organizeRepository.Context.Updateable(entity)
                .IgnoreColumns(ignoreAllNullColumns: true)
                .CallEntityMethod(m => m.Delete()).ExecuteCommandAsync();
            if (!(isOk > 0))
                throw YNTKException.Oh(ErrorCode.D2012);

            //删除组织服务开通记录
            int count = await _organizeOpenRepository.DeleteAsync(r => r.OrganizeId == id);
            //if (!(count > 0)) throw YNTKException.Oh(ErrorCode.D2028);
            //同步删除mongodb中存的组织信息
            try
            {
                if (await _mongoDBRepository.ExistsAsync(_collectionName))
                {
                    await _mongoDBRepository.DeleteAsync(_collectionName, id);
                }
            }
            catch
            {
            }
        }

        /// <summary>
        /// 更新组织状态(启用/禁用)
        /// </summary>
        /// <param name="id">组织id</param>
        /// <returns></returns>
        [HttpPut("platform/state")]
        public async Task UpdateState([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh("没有启用/禁用组织的权限");

                if (!await _organizeRepository.AnyAsync(u => u.Id == id && u.DeleteMark == null))
                    throw YNTKException.Oh(ErrorCode.D2002);
                var isOk = await _organizeRepository.Context.Updateable<OrganizeEntity>().SetColumns(it => new OrganizeEntity()
                {
                    EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1),
                    LastModifyUserId = userId,
                    LastModifyTime = SqlFunc.GetDate()
                }).Where(it => it.Id == id).ExecuteCommandAsync();
                if (!(isOk > 0))
                    throw YNTKException.Oh(ErrorCode.D2011);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"更新组织状态发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 生成授权TK码
        /// </summary>
        /// <returns></returns>
        [HttpGet("platform/tkcode")]
        public async Task<TkResult<string>> GenerateAuthorizationTkCode([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh(ErrorCode.D2027);
                var organize = await _organizeRepository.FirstOrDefaultAsync(u => u.Id == id && u.DeleteMark == null);
                if (organize==null)throw YNTKException.Oh(ErrorCode.D2002);
                string text = $"运营平台:云南通科科技有限公司,授权组织:{organize.OrganizeName},授权组织id:{organize.Id},组织代码:{organize.EnCode}";
                //基于Sha1加密,返回加密后的十六进制的哈希散列
                string tkCode = text.CheckSignature();
                //再次md5加密
                string md5Code = MD5Encryption.Encrypt(tkCode);
                return TkResult<string>.Success(md5Code, "授权TK码生成成功！");
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"生成授权TK码发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 开通组织服务
        /// </summary>
        /// <param name="open">开通服务请求模型</param>
        /// <returns></returns>
        [HttpPut("platform/open")]
        public async Task Open(OpenOrganizeRequestModel open)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh(ErrorCode.D2022);
                var organize = await _organizeRepository.FirstOrDefaultAsync(r => r.Id == open.id && r.DeleteMark == null);
                if (organize == null) throw YNTKException.Oh(ErrorCode.D2002);
                if (organize.State== OrganizeStateEnum.HasBeenOpened.GetHashCode()) 
                    throw YNTKException.Oh(ErrorCode.D2021);           
                
                //添加开通服务记录
                var entity = open.Adapt<OrganizeOpenRecordEntity>();
                entity.OperatingTime = DateTime.Now;//开通/终止时间
                //服务类型(0.开通服务 1.服务到期 2.服务终止)
                entity.ServiceType = OrganizeServiceTypeEnum.OpenService.GetHashCode();
                entity.OrganizeId = open.id;//所属组织id
                var isOk = await _organizeOpenRepository.Context.Insertable(entity)
                   .CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
                _ = isOk ?? throw YNTKException.Oh(ErrorCode.D2023);

                //修改组织服务信息
                organize.AuthorizationCode = open.authorizationCode;//授权TK码
                organize.FirstOpeningDate = organize.FirstOpeningDate?? entity.OperatingTime;//首次开通日期
                organize.OpeningDate = entity.OperatingTime;//最近一次开通日期
                organize.MandateStart = entity.MandateStart;//授权期限起
                organize.MandateEnd = entity.MandateEnd;//授权期限止
                organize.State = OrganizeStateEnum.HasBeenOpened.GetHashCode();//状态(0.未开通 1.已开通 2.服务到期)
                var edit = await _organizeRepository.Context.Updateable(organize)
                    .IgnoreColumns(ignoreAllNullColumns: true)
                    .CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync();
                if (!(edit > 0))
                    throw YNTKException.Oh(ErrorCode.D2010);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"开通组织服务发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 手动终止组织服务,非必要不要使用
        /// </summary>
        /// <param name="stop">手动停止组织服务</param>
        /// <returns></returns>
        [HttpPut("platform/stop")]
        public async Task Stop(TerminationOrganizeRequestModel stop)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                if (authenticationType != "0" && authenticationType != "1")
                    throw YNTKException.Oh(ErrorCode.D2022);
                var organize = await _organizeRepository.FirstOrDefaultAsync(r => r.Id == stop.id && r.DeleteMark == null);
                if (organize == null) throw YNTKException.Oh(ErrorCode.D2002);
                if (organize.State != OrganizeStateEnum.HasBeenOpened.GetHashCode())
                    throw YNTKException.Oh(ErrorCode.D2024);

                //添加终止服务记录
                var entity = stop.Adapt<OrganizeOpenRecordEntity>();
                entity.OperatingTime = DateTime.Now;//开通/终止时间
                //服务类型(0.开通服务 1.服务到期 2.服务终止)
                entity.ServiceType = OrganizeServiceTypeEnum.ServiceTermination.GetHashCode();
                entity.OrganizeId = stop.id;//所属组织id
                entity.MandateStart = organize.MandateStart;//授权期限起
                entity.MandateEnd = organize.MandateEnd;//授权期限止
                entity.AuthorizationCode = organize.AuthorizationCode;//授权TK码
                var isOk = await _organizeOpenRepository.Context.Insertable(entity)
                   .CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
                _ = isOk ?? throw YNTKException.Oh(ErrorCode.D2025);

                //修改组织服务信息 状态(0.未开通 1.已开通 2.服务到期 3.服务终止)
                organize.State = OrganizeStateEnum.ServiceTermination.GetHashCode();
                var edit = await _organizeRepository.Context.Updateable(organize)
                    .IgnoreColumns(ignoreAllNullColumns: true)
                    .CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync();
                if (!(edit > 0))
                    throw YNTKException.Oh(ErrorCode.D2010);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"手动终止组织服务发生异常：{ex.Message}");
            }
        }
        #endregion

        #region 企业端
        /// <summary>
        /// 根据组织授权tk码获取组织信息
        /// </summary>
        /// <param name="code">授权tk码</param>
        /// <returns></returns>
        [HttpGet("getinfo/{code}")]
        [AllowAnonymous]
        public async Task<TkResult<OrganizeInfoDto>> GetInfo([Required] string code)
        {
            //获取组织详细
            var organize = await _organizeRepository.FirstOrDefaultAsync(r => r.AuthorizationCode == code && r.DeleteMark == null);
            if (organize == null)
            {
                //有可能更改过授权tk码
                var open = await _organizeOpenRepository.FirstOrDefaultAsync(r => r.AuthorizationCode == code && r.DeleteMark == null);
                if(open==null) throw YNTKException.Oh(ErrorCode.D2002);
                organize = await _organizeRepository.FirstOrDefaultAsync(r=>r.Id==open.Id && r.DeleteMark==null);
                if (organize == null) throw YNTKException.Oh(ErrorCode.D2002);
            }
           
            if(organize.State== OrganizeStateEnum.DidOpen.GetHashCode())
                throw YNTKException.Oh(ErrorCode.D2039);
            if (organize.State == OrganizeStateEnum.ServiceMaturity.GetHashCode())
                throw YNTKException.Oh(ErrorCode.D2040);
            if (organize.State == OrganizeStateEnum.ServiceTermination.GetHashCode())
                throw YNTKException.Oh(ErrorCode.D2041);
            var result = organize.Adapt<OrganizeInfoDto>();
            result.stateText = EnumHelper.GetEnumDescriptionString
                (result.state, typeof(OrganizeStateEnum));
            //从mongodb数据库获取组织详细信息
            if (await _mongoDBRepository.ExistsAsync(_collectionName))
            {
                var mongo = await _mongoDBRepository.GetAsync(_collectionName, r => r.Id == organize.Id);
                if (mongo != null)
                {
                    result.logId = mongo.LogId;
                    result.introduction = mongo.Introduction;
                    result.scopeBusiness = mongo.ScopeBusiness;
                    result.address = mongo.Address;
                    result.information = mongo.Information;
                }
            }
            return TkResult<OrganizeInfoDto>.Success(result);
        }

        /// <summary>
        /// 获取组织log路径和授权tk码
        /// </summary>
        /// <param name="id">组织id</param>
        /// <returns></returns>
        [NonAction]
        public async Task<(string,string)> GetLogPath(string id)
        {
            var organize = await _organizeRepository.FirstOrDefaultAsync(r => r.Id == id && r.DeleteMark == null);
            var mongo = await _mongoDBRepository.GetAsync(_collectionName, r => r.Id == id);
            return (mongo?.LogId ?? "", organize?.AuthorizationCode ?? "");
        }

        /// <summary>
        /// 获取组织详细信息
        /// </summary>
        /// <param name="id">组织id</param>
        /// <returns></returns>
        [HttpGet("get/{id}")]
        public async Task<TkResult<OrganizeInfoDto>> Get([Required] string id)
        {
            //获取组织详细
            var organize = await _organizeRepository.FirstOrDefaultAsync(r => r.Id ==id && r.DeleteMark == null);
            if (organize == null) throw YNTKException.Oh(ErrorCode.D2002);
            var result = organize.Adapt<OrganizeInfoDto>();
            result.stateText = EnumHelper.GetEnumDescriptionString
                (result.state, typeof(OrganizeStateEnum));
            //从mongodb数据库获取组织详细信息
            if (await _mongoDBRepository.ExistsAsync(_collectionName))
            {
                var mongo = await _mongoDBRepository.GetAsync(_collectionName,r=>r.Id==id);
                if (mongo != null)
                {
                    result.logId = mongo.LogId;
                    result.introduction = mongo.Introduction;
                    result.scopeBusiness = mongo.ScopeBusiness;
                    result.address = mongo.Address;
                    result.information = mongo.Information;                              
                }
            }
            return TkResult<OrganizeInfoDto>.Success(result);
        }

        /// <summary>
        /// 获取组织文件数据
        /// </summary>
        /// <param name="id">组织id唯一标识</param>
        /// <param name="classifyId">组织文件分类id</param>
        /// <returns></returns>
        [HttpGet("getfiles/{id}&{classifyId}")]
        public async Task<TkResult<List<OrganizeFileListDto>>> GetFiles([Required] string id,string classifyId)
        {
            try
            {
                var organize = await _organizeRepository.FirstOrDefaultAsync(r => r.Id == id && r.DeleteMark == null);
                if (organize == null) throw YNTKException.Oh(ErrorCode.D2002);
                Expression<Func<OrganizeFileEntity, bool>> where = r => r.OrganizeId == id;
                if (!string.IsNullOrWhiteSpace(classifyId))
                {
                    string queryClassifyId = await _dictionaryService.GetIdAsync(classifyId, id);
                    where = where.And(m => m.ClassifyId == queryClassifyId);
                }
                //先从mongodb中获取
                var files = await _organizeFileMongoDBRepository.GetListAsync(_orgFiles, where);
                if (!files.Any()) files = await _organizeFilerepository.Entities.Where(where).ToListAsync();
                var result = files.Adapt<List<OrganizeFileListDto>>();
                if (result.Any())
                {
                    var classifyIds = result.Select(r => r.classifyId.Split(',').ToList())
                       ?.SelectMany(r => r).Distinct().ToList();
                    var classifys = await _dictionaryService.GetDictionaryListByIds(classifyIds);
                    result.ForEach(file =>
                    {
                        file.classifyName = string.Join('/', classifys?
                               .Where(r => file.classifyId.Split(',').ToList().Contains(r.Id))
                               ?.Select(r => r.Name).ToList());
                    });
                }
                return TkResult<List<OrganizeFileListDto>>.Success(result);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取组织文件数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 保存组织信息
        /// </summary>
        /// <param name="save">组织信息维护请求模型</param>
        /// <returns></returns>
        [HttpPost("save/info")]
        public async Task Save(OrganizeInfoRequestModel save)
        {
            try
            {
                var organize = await _organizeRepository.FirstOrDefaultAsync(r => r.Id == save.id && r.DeleteMark == null);
                if (organize == null) throw YNTKException.Oh(ErrorCode.D2002);
                //将组织详细信息保存到mongodb中
                var mongodbEntity = save.Adapt<OrganizeMongodbEntity>();
                mongodbEntity.OrganizeId = save.id;
                mongodbEntity.Id = save.id;
                mongodbEntity.LastModifyTime = DateTime.Now;//最近一次修改时间
                var update = await _mongoDBRepository.UpdateAsync(mongodbEntity, _collectionName, m => m.Id == save.id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.D2038);                           
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"保存组织信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加组织文件
        /// </summary>
        /// <param name="model">添加组织文件请求模型</param>
        /// <returns></returns>
        [HttpPut("add/file")]
        public async Task AddFile(AddOrganizeFileRequestModel model)
        {
            try
            {
                var organize = await _organizeRepository.FirstOrDefaultAsync(r => r.Id == model.id && r.DeleteMark == null);
                if (organize == null) throw YNTKException.Oh(ErrorCode.D2002);
                var entity= model.Adapt<OrganizeFileEntity>();
                entity.Id = YitIdHelper.NextId().ToString();
                entity.OrganizeId = model.id;//所属组织id
                entity.CreatorTime = DateTime.Now;
                var isOk = await _organizeFilerepository.Context.Insertable(entity)
                   .ExecuteReturnEntityAsync();
                _ = isOk ?? throw YNTKException.Oh(ErrorCode.D2036);
                var result = await _organizeFileMongoDBRepository.AddAsync(entity, _orgFiles);
                if (!result) throw YNTKException.Oh(ErrorCode.D2037);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加组织文件发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除组织文件
        /// </summary>
        /// <param name="id">记录id</param>
        /// <returns></returns>
        [HttpDelete("delete/{id}")]
        public async Task DeleteFiles([Required] string id)
        {
            try
            {
                var entity = await _organizeFileMongoDBRepository.GetAsync(_orgFiles, m => m.Id == id);
                if (entity == null) entity = await _organizeFilerepository.FirstOrDefaultAsync(r=>r.Id==id);
                if (entity != null)
                {
                    await _organizeFilerepository.DeleteAsync(r=>r.Id==id);
                    await _organizeFileMongoDBRepository.DeleteAsync(_orgFiles,m=>m.Id==id);
                    //删除文件
                    string filePath = FileVariable.OrganizationFilePath + entity.FileDirectory + entity.SaveFileName;
                    if (File.Exists(filePath)) File.Delete(filePath);
                }
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除组织文件发生异常：{ex.Message}");
            }
        }
        #endregion

        #region 组织资料(管理手册、方针目标、法律法规、资质荣誉)
        /// <summary>
        /// 分页获取组织资料(管理手册、方针目标、法律法规、资质荣誉)数据
        /// </summary>
        /// <param name="query">查询组织资料请求模型</param>
        /// <returns></returns>
        [HttpPost("data/gets")]
        public async Task<TkPageResult<OrganizeDataListDto>> GetOrganizeDataList([FromBody] QueryOrganizeDataFilterRequestModel query)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;

                #region 拼接查询条件
                Expression<Func<OrganizeDataEntity, bool>> where = r =>
                r.OrganizeId == organizeId && r.Type==query.type.GetHashCode() && r.DeleteMark == null &&
                (r.CreatorUserId == userId || (r.CreatorUserId != userId && r.EnabledMark == 1));
                if (query.enabledMark == 1) where = where.And(m => m.EnabledMark == 1);
                if (query.enabledMark == 0) where = where.And(m => m.EnabledMark != 1);
                if (!string.IsNullOrWhiteSpace(query.classifyId))
                {
                    string queryClassifyId = await _dictionaryService.GetIdAsync(query.classifyId, organizeId);
                    where = where.And(m => m.ClassifyId == queryClassifyId);
                }
                if (query.startTime != null) where = where.And(m => m.CreatorTime >= query.startTime);
                if (query.endTime != null) where = where.And(m => m.CreatorTime <= query.endTime);
                if (!string.IsNullOrWhiteSpace(query.keyword))
                    where = where.And(m => m.Title.Contains(query.keyword) || m.Source.Contains(query.keyword) ||
                    m.Code.Contains(query.keyword) || m.ReleaseUnit.Contains(query.keyword) ||
                    m.ApplicableProvision.Contains(query.keyword));
                #endregion

                var pageList = new SqlSugarPagedList<OrganizeDataListDto>();
                #region 从mongodb中获取组织资料数据
                //排序生成器
                var builderSort = Builders<OrganizeDataEntity>.Sort;
                //排序约束   Ascending 正序    Descending 倒序
                var sort = builderSort.Ascending(r => r.SortCode);
                //Item1.结果集 Item2.总条数 Item3.总页数
                (List<OrganizeDataEntity>, int, int) result =
                    await _dataMongoDbRepository.GetListAsync(_data,
                    where, query.currentPage, query.pageSize, null, sort);
                pageList.list = result.Item1.Adapt<List<OrganizeDataListDto>>();
                pageList.pagination = new PagedModel()
                {
                    PageIndex = query.currentPage,
                    PageSize = query.pageSize,
                    Total = result.Item2,
                    PageCount = result.Item3
                };
                #endregion

                if (pageList.list == null || pageList.list.Count() <= 0)
                {
                    #region 从sqlserver数据库中获取组织资料数据
                    var sqlResult = await _dataRepository.Entities.Where(where)
                         .OrderBy(r => r.SortCode, OrderByType.Asc)
                         //.OrderBy(r => r.CreatorTime, OrderByType.Desc)
                         .ToPagedListAsync(query.currentPage, query.pageSize);
                    pageList.list = sqlResult.list.Adapt<List<OrganizeDataListDto>>();
                    pageList.pagination = sqlResult.pagination;
                    #endregion
                }

                #region 处理组织资料返回数据
                if (pageList.list.Any())
                {
                    var classifyIds = pageList.list.Where(r=>!string.IsNullOrWhiteSpace(r.classifyId))?.ToList()
                        ?.Select(r => r.classifyId.Split(',').ToList())?.SelectMany(r => r)?.Distinct()?.ToList();
                    var classifys = await _dictionaryService.GetDictionaryListByIds(classifyIds);
                    var userIds = pageList.list.Select(r => r.creatorUserId).Distinct().ToList();
                    var users = await _userRepository.Entities.Where(u => userIds.Contains(u.Id) && u.DeleteMark == null).ToListAsync();
                    var mechanismIds = pageList.list.Where(r => !string.IsNullOrWhiteSpace(r.applicableScope))
                        ?.ToList().Select(r => r.applicableScope.Split(',').ToList())?.SelectMany(r => r)?.Distinct().ToList();
                    var dic = await GetMechanismIdsAsync(mechanismIds, organizeId);
                    var values = new List<(string, string)>();
                    foreach (var data in pageList.list)
                    {
                        data.typeText = EnumHelper.GetEnumDescriptionString(data.type, typeof(OrganizeDataTypeEnum));
                        if (!string.IsNullOrWhiteSpace(data.classifyId))
                            data.classifyName = classifys.FirstOrDefault(r => r.Id == data.classifyId.Split(',').Last())?.Name;
                        if (!string.IsNullOrWhiteSpace(data.creatorUserId))
                            data.creatorUserName = users?.FirstOrDefault(r => r.Id == data.creatorUserId)?.RealName;
                        if(data.type == OrganizeDataTypeEnum.LawsRegulations.GetHashCode())
                        {
                            if (!string.IsNullOrWhiteSpace(data.applicableScope))
                            {
                                values = dic?.Where(r => data.applicableScope.Split(',').ToList().Contains(r.Key))
                                    ?.Select(r => r.Value).ToList();
                                if (values != null && values.Count > 0)
                                    data.applicableScopeText = string.Join(',', values.Select(r => r.Item2).ToList());
                            }
                            else data.applicableScopeText = "全组织";
                        }                       
                    }
                }
                #endregion

                return TkPageResult<OrganizeDataListDto>.Success(pageList);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"分页获取{query.type.GetDescription()}数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 获取组织资料(管理手册、方针目标、法律法规、资质荣誉)详细信息
        /// </summary>
        /// <param name="type">组织资料类型(0.管理手册 1.方针目标 2.法律法规 3.资质荣誉)</param>
        /// <param name="id">组织资料id</param>
        /// <returns></returns>
        [HttpGet("data/get/{type}/{id}")]
        public async Task<TkResult<OrganizeDataDto>> GetOrganizeDataInfo([Required] OrganizeDataTypeEnum type, [Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;

                var entity = await GetOrganizeDataInfoAsync(r => r.Type==type.GetHashCode() && r.Id == id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.D2044);
                var data = entity.Adapt<OrganizeDataDto>();

                #region 处理访客记录详细返回信息
                data.typeText = EnumHelper.GetEnumDescriptionString(data.type, typeof(OrganizeDataTypeEnum));
                if (!string.IsNullOrWhiteSpace(data.classifyId))
                    data.classifyName = (await _dictionaryService.GetDictionaryInfoAsync(data.classifyId.Split(',').Last()))?.Name;
                if (!string.IsNullOrWhiteSpace(data.creatorUserId))
                    data.creatorUserName = (await _userRepository.FirstOrDefaultAsync(r=>r.Id== data.creatorUserId))?.RealName;
                //法律法规适用范围处理
                if(data.type== OrganizeDataTypeEnum.LawsRegulations.GetHashCode())
                {
                    if (!string.IsNullOrWhiteSpace(data.applicableScope))
                    {
                        var dic = await GetMechanismIdsAsync(data.applicableScope.Split(',').ToList(), organizeId);
                        var values = dic.Values.ToList();
                        data.applicableScopeText = string.Join(',', values.Select(r => r.Item2).ToList());
                        data.scopeMechanismValue = values.Select(r => r.Item1.Split(',').ToArray())?.ToList();
                    }
                    else data.applicableScopeText = "全组织";                   
                }              
                #endregion

                //获取组织资料相关附件数据
                var fileData = await GetOrganizeDataFilesListAsync(id);
                data.fileData = fileData.Adapt<List<FileListDto>>();

                return TkResult<OrganizeDataDto>.Success(data);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取{type.GetDescription()}详细信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加组织资料(管理手册、方针目标、法律法规、资质荣誉)
        /// </summary>
        /// <param name="input">添加组织资料请求模型</param>
        /// <returns></returns>
        [HttpPost("data/add")]
        public async Task Add([FromBody] AddOrganizeDataRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;

                if(input.type== OrganizeDataTypeEnum.LawsRegulations && string.IsNullOrWhiteSpace(input.classifyId))
                    throw YNTKException.Oh(ErrorCode.D2054);
                if ((await GetOrganizeDataInfoAsync(r => r.OrganizeId == organizeId && r.MechanismId == mechanismId &&
                r.Type == input.type.GetHashCode() && r.Title == input.title && r.DeleteMark == null)) != null)
                    throw YNTKException.Oh(ErrorCode.D2045);

                var entity = input.Adapt<OrganizeDataEntity>();
                entity.OrganizeId = organizeId;
                entity.MechanismId = mechanismId;

                //保存组织资料到sqlserver
                var isOk = await _dataRepository.Context.Insertable(entity)
                    .CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
                _ = isOk ?? throw YNTKException.Oh(ErrorCode.D2046);

                //保存组织资料到mongodb
                entity = isOk;
                var result = await _dataMongoDbRepository.AddAsync(entity, _data);
                if (!result) throw YNTKException.Oh(ErrorCode.D2047);

                //保存组织资料相关附件
                await SaveOrganizeDataFilesAsync(entity.Id, userId, input.fileData);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加{input.type.GetDescription()}信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改组织资料(管理手册、方针目标、法律法规、资质荣誉)
        /// </summary>
        /// <param name="input">修改组织资料请求模型</param>
        /// <returns></returns>
        [HttpPut("data/update")]
        public async Task UpdateData([FromBody] UpdateOrganizeDataRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;

                if (input.type == OrganizeDataTypeEnum.LawsRegulations && string.IsNullOrWhiteSpace(input.classifyId))
                    throw YNTKException.Oh(ErrorCode.D2054);
                var entity = await GetOrganizeDataInfoAsync(r => r.Id == input.id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.D2044);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);
                if ((await GetOrganizeDataInfoAsync(r => r.OrganizeId == organizeId && r.MechanismId == mechanismId &&
                r.Type == input.type.GetHashCode() && r.Title == input.title && r.Id!=input.id && r.DeleteMark == null)) != null)
                    throw YNTKException.Oh(ErrorCode.D2045);

                entity = input.Mapper(entity);
                //保存组织资料到sqlserver
                entity.OrganizeId = organizeId;
                entity.MechanismId = mechanismId;
                entity.LastModifyTime = DateTime.Now;
                entity.LastModifyUserId = userId;
                var isOK = await _dataRepository.Context.Updateable(entity)
                .IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.D2048);

                //保存组织资料到mongodb
                var update = await _dataMongoDbRepository.UpdateAsync(entity, _data, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.D2049);

                //保存组织资料相关附件
                await SaveOrganizeDataFilesAsync(entity.Id, userId, input.fileData);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改{input.type.GetDescription()}信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除组织资料(管理手册、方针目标、法律法规、资质荣誉)
        /// </summary>
        /// <param name="type">组织资料类型(0.管理手册 1.方针目标 2.法律法规 3.资质荣誉)</param>
        /// <param name="id">组织资料id</param>
        /// <returns></returns>
        [HttpDelete("data/delete/{type}/{id}")]
        public async Task DeleteData([Required] OrganizeDataTypeEnum type, [Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;

                var entity = await GetOrganizeDataInfoAsync(r => r.Id == id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.D2044);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //从sqlserver中删除
                var isOk = await _dataRepository.Context.Deleteable(entity).ExecuteCommandAsync();
                if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.D2050);

                //从mongodb中删除
                var delete = await _dataMongoDbRepository.DeleteAsync(_data, m => m.Id == id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.D2051);

                //删除组织资料相关附件数据
                await DeleteOrganizeDataFilesAsync(id);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除{type.GetDescription()}发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 更新组织资料(管理手册、方针目标、法律法规、资质荣誉)状态(启用/禁用)
        /// </summary>
        /// <param name="type">组织资料类型(0.管理手册 1.方针目标 2.法律法规 3.资质荣誉)</param>
        /// <param name="id">访客记录id</param>
        /// <returns></returns>
        [HttpPut("data/state/{type}/{id}")]
        public async Task UpdateDataState([Required] OrganizeDataTypeEnum type,[Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;

                var entity = await GetOrganizeDataInfoAsync(r => r.Id == id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.D2044);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                var isOk = await _dataRepository.Context.Updateable<OrganizeDataEntity>()
               .SetColumns(it => new OrganizeDataEntity()
               {
                   EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1),
                   LastModifyUserId = userId,
                   LastModifyTime = SqlFunc.GetDate()
               }).Where(it => it.Id == id).ExecuteCommandAsync();
                if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.D2052);

                entity.EnabledMark = entity.EnabledMark == 1 ? 0 : 1;
                entity.LastModifyTime = DateTime.Now;
                entity.LastModifyUserId = userId;
                var update = await _dataMongoDbRepository.UpdateAsync(entity, _data, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.D2053);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"更新{type.GetDescription()}状态(启用/禁用)发生异常：{ex.Message}");
            }
        }


        /// <summary>
        /// 根据条件获取组织资料信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<OrganizeDataEntity> GetOrganizeDataInfoAsync(Expression<Func<OrganizeDataEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _dataMongoDbRepository.GetAsync(_data, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _dataRepository.FirstOrDefaultAsync(where);
            return entity;
        }

        #region 组织资料相关附件
        /// <summary>
        /// 获取组织资料相关附件数据
        /// </summary>
        /// <param name="dataId">组织资料id</param>
        /// <returns></returns>
        private async Task<List<OrganizeDataFilesEntity>> GetOrganizeDataFilesListAsync(string dataId)
        {
            //从mongodb中获取附件数据
            var result = await _dataFilesMongoDbRepository.GetListAsync(_dataFiles, r => r.OrganizeDataId == dataId);
            if (!result.Any())
            {
                //从sqlserver数据库中获取附件数据
                result = await _dataFilesRepository.Entities.Where(r => r.OrganizeDataId == dataId).ToListAsync();
            }
            return result;
        }

        /// <summary>
        /// 保存组织资料相关附件
        /// </summary>
        /// <param name="dataId">组织资料id</param>
        /// <param name="userId">当前用户id</param>
        /// <param name="fileData">相关附件数据</param>
        /// <returns></returns>
        private async Task SaveOrganizeDataFilesAsync(string dataId, string userId, List<FileRequestModel> fileData)
        {
            try
            {
                _dataFilesRepository.Ado.BeginTran();
                //删除原数据
                await _dataFilesMongoDbRepository.DeleteAsync(_dataFiles, r => r.OrganizeDataId == dataId);
                await _dataFilesRepository.DeleteAsync(r => r.OrganizeDataId == dataId);
                if (fileData != null && fileData.Count > 0)
                {
                    var files = new List<OrganizeDataFilesEntity>();
                    var file = new OrganizeDataFilesEntity();
                    fileData.ForEach(item =>
                    {
                        file = item.Adapt<OrganizeDataFilesEntity>();
                        file.Id = YitIdHelper.NextId().ToString();
                        file.OrganizeDataId = dataId;
                        file.CreatorUserId = userId;
                        file.CreatorTime = DateTime.Now;
                        files.Add(file);
                    });
                    //保存到sqlserver                 
                    var isOk = await _dataFilesRepository.Context.Insertable(files).ExecuteCommandAsync();
                    if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.D2042);
                    //保存到mongodb
                    var succeed = await _dataFilesMongoDbRepository.AddListAsync(files, _dataFiles);
                    if (!succeed) throw YNTKException.Oh(ErrorCode.D2043);
                }
                _dataFilesRepository.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                _dataFilesRepository.Ado.RollbackTran();
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"保存组织资料相关附件发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除组织资料相关附件数据
        /// </summary>
        /// <param name="dataId">组织资料id</param>
        /// <returns></returns>
        private async Task DeleteOrganizeDataFilesAsync(string dataId)
        {
            var result = await GetOrganizeDataFilesListAsync(dataId);
            if (result.Any())
            {
                //删除原数据
                await _dataFilesMongoDbRepository.DeleteAsync(_dataFiles, r => r.OrganizeDataId == dataId);
                await _dataFilesRepository.DeleteAsync(r => r.OrganizeDataId == dataId);
                //删除文件
                string filePath = "";//文件路径
                foreach (var file in result)
                {
                    filePath = FileVariable.OrganizationFilePath + file.FileDirectory + file.SaveFileName;
                    if (File.Exists(filePath)) File.Delete(filePath);
                }
            }
        }
        #endregion
        #endregion

        /// <summary>
        /// 获取组织下拉数据
        /// </summary>
        /// <param name="keyword">模糊搜索关键字</param>
        /// <returns></returns>
        [HttpGet("getdropdowndata")]
        public async Task<TkResult<List<OrganizeSelectListDto>>> GetSelectData(string keyword)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            List<OrganizeSelectListDto> result = null;
            if ((authenticationType == "4" || authenticationType == "5") && string.IsNullOrWhiteSpace(organizeId))
                return TkResult<List<OrganizeSelectListDto>>.Success(result);
            var data = await _organizeRepository.Entities
                .WhereIF(authenticationType == "2" || authenticationType == "3", r => r.Id == organizeId)
                .WhereIF(authenticationType == "4" && !string.IsNullOrWhiteSpace(organizeId), r => r.Id == organizeId)
                .WhereIF(!string.IsNullOrWhiteSpace(keyword), r => r.FullName.Contains(keyword) ||
                r.OrganizeName.Contains(keyword) && r.EnCode.Contains(keyword))
                .Where(r => r.DeleteMark == null)
                .OrderBy(r => r.CreatorTime, OrderByType.Desc)
                .ToListAsync();
            result = data.Adapt<List<OrganizeSelectListDto>>();
            return TkResult<List<OrganizeSelectListDto>>.Success(result);
        }


        #region 定置定位文件
        /// <summary>
        /// 获取定置定位文件数据
        /// </summary>
        /// <param name="classifyId">定置定位文件分类id</param>
        /// <returns></returns>
        [HttpGet("orientationfiles/{classifyId}")]
        public async Task<TkResult<List<OrientationFileListDto>>> GetOrientationFileList([Required]string classifyId)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;

                //先从mongodb中获取
                var files = await _orientationFilesMongoDbRepository.GetListAsync(_orientationFiles, m=>m.OrganizeId==organizeId && m.ClassifyId==classifyId);
                if (!files.Any()) files = await _orientationFilesRepository.Entities.Where(r => r.OrganizeId == organizeId && r.ClassifyId == classifyId).ToListAsync();
                var result = files.Adapt<List<OrientationFileListDto>>();
                if (result.Any())
                {
                    var mechanismIds = result.Where(r => !string.IsNullOrWhiteSpace(r.mechanismId))
                        ?.Select(r => r.mechanismId.Split(',').ToList())
                        ?.SelectMany(r => r).Distinct().ToList();
                    var mechanisms = mechanismIds == null || mechanismIds.Count <= 0
                        ? new List<MechanismEntity>() :
                        await _mechanismMongoDbRepository.GetListAsync(_mechanisms, m=> mechanismIds.Contains(m.Id));
                    var classifyIds = result.Select(r => r.classifyId.Split(',').ToList())
                       ?.SelectMany(r => r).Distinct().ToList();
                    var classifys = await _dictionaryService.GetDictionaryListByIds(classifyIds);
                    var creatorUserIds = result.Select(r => r.creatorUserId).Distinct().ToList();
                    var users = await _userRepository.Entities.Where(r=> creatorUserIds.Contains(r.Id) && r.DeleteMark==null).ToListAsync();
                    result.ForEach(file =>
                    {
                        file.classifyName = string.Join('/', classifys?
                               .Where(r => file.classifyId.Split(',').ToList().Contains(r.Id))
                               ?.Select(r => r.Name).ToList());
                        if (!string.IsNullOrWhiteSpace(file.mechanismId))
                        {
                            file.mechanismName = string.Join('/', mechanisms
                                ?.Where(r => file.mechanismId.Split(',').ToList().Contains(r.Id))
                                ?.Select(r => r.Name)?.ToList());
                        }
                        if (!string.IsNullOrWhiteSpace(file.creatorUserId))
                            file.creatorUserName = users?.FirstOrDefault(r => r.Id == file.creatorUserId)?.RealName;
                    });
                }
                return TkResult<List<OrientationFileListDto>>.Success(result);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取定置定位文件数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加定置定位文件
        /// </summary>
        /// <param name="model">上传定置定位文件请求模型</param>
        /// <returns></returns>
        [HttpPut("orientationfiles/add")]
        public async Task AddOrientationFile(AddOrientationFileRequestModel model)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;

                var entity = model.Adapt<OrientationFilesEntity>();
                entity.Id = YitIdHelper.NextId().ToString();
                entity.OrganizeId = organizeId;//所属组织id
                entity.MechanismId = mechanismId;
                entity.CreatorUserId = userId;
                entity.CreatorTime = DateTime.Now;
                var isOk = await _orientationFilesRepository.Context.Insertable(entity).ExecuteReturnEntityAsync();
                _ = isOk ?? throw YNTKException.Oh(ErrorCode.D2055);
                var result = await _orientationFilesMongoDbRepository.AddAsync(entity, _orientationFiles);
                if (!result) throw YNTKException.Oh(ErrorCode.D2056);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加定置定位文件发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除定置定位文件
        /// </summary>
        /// <param name="id">定置定位文件id</param>
        /// <returns></returns>
        [HttpDelete("orientationfiles/delete/{id}")]
        public async Task DeleteOrientationFile([Required] string id)
        {
            try
            {
                var entity = await _orientationFilesMongoDbRepository.GetAsync(_orientationFiles, m => m.Id == id);
                if (entity == null) entity = await _orientationFilesRepository.FirstOrDefaultAsync(r => r.Id == id);
                if (entity != null)
                {
                    await _orientationFilesRepository.DeleteAsync(r => r.Id == id);
                    await _orientationFilesMongoDbRepository.DeleteAsync(_orientationFiles, m => m.Id == id);
                    //删除文件
                    string filePath = FileVariable.OrganizationFilePath + entity.FileDirectory + entity.SaveFileName;
                    if (File.Exists(filePath)) File.Delete(filePath);
                }
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除定置定位文件发生异常：{ex.Message}");
            }
        }
        #endregion

        /// <summary>
        /// 处理机构id拼接上所有父级id
        /// </summary>
        /// <param name="ids">id集合(最后一级的id)</param>
        /// <param name="organizeId">组织id</param>
        /// <returns>key.id  value.(Item1.拼接上所有父级的id,Item2.最后一级的机构名称)</returns>
        private async Task<Dictionary<string, (string, string)>> GetMechanismIdsAsync(List<string> ids, string organizeId)
        {
            var dic = new Dictionary<string, (string, string)>() { { "0", ("0", "") } };
            if (!ids.Any()) return null;
            dic = ids.ToDictionary(x => x, x => (x, ""));
            var data = await _mechanismMongoDbRepository.GetListAsync(_mechanisms, m => m.OrganizeId == organizeId && m.DeleteMark == null);      
            if (!data.Any()) return dic;
            var list = new List<MechanismEntity>();
            string id = "";
            foreach (KeyValuePair<string, (string, string)> item in dic)
            {
                id = item.Value.Item1;
                //获取所有上级包括自己
                list = data.TreeWhere(r => r.Id == id, r => r.Id, r => r.ParentId);
                //顺序反转
                list.Reverse();
                id = string.Join(',', list.Select(r => r.Id).ToList());
                dic[item.Key] = (id, list.Last().Name);
            }
            return dic;
        }


        #region PublicMethod
        /// <summary>
        /// 根据组织id集合获取组织数据
        /// </summary>
        /// <param name="ids">组织id集合</param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<OrganizeEntity>> GetOrganizeListByIds(List<string> ids)
        {
            var result = new List<OrganizeEntity>();
            if (ids == null || ids.Count <= 0) return result;
            result = await _organizeRepository.Entities
                .Where(r => ids.Contains(r.Id) && r.DeleteMark == null).ToListAsync();
            return result;
        }      

        /// <summary>
        /// 是否机构主管
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        [NonAction]
        public async Task<bool> GetIsManagerByUserId(string userId)
        {
            return await _organizeRepository.AnyAsync(o => o.EnabledMark.Equals(1) && o.DeleteMark == null && o.ManagerId == userId);
        }

        /// <summary>
        /// 获取机构列表(其他服务使用)
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<List<OrganizeEntity>> GetListAsync()
        {
            return await _organizeRepository.Where(t => t.EnabledMark.Equals(1) && t.DeleteMark == null).OrderBy(o => o.SortCode).ToListAsync();
        }

        /// <summary>
        /// 获取公司列表(其他服务使用)
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<List<OrganizeEntity>> GetCompanyListAsync()
        {
            return await _organizeRepository.Where(t => t.Category.Equals("company") && t.EnabledMark.Equals(1) && t.DeleteMark == null).OrderBy(o => o.SortCode).ToListAsync();
        }

        /// <summary>
        /// 下属机构
        /// </summary>
        /// <param name="organizeId">机构ID</param>
        /// <param name="isAdmin">是否管理员</param>
        /// <returns></returns>
        [NonAction]
        public async Task<string[]> GetSubsidiary(string organizeId, bool isAdmin)
        {
            var data = await _organizeRepository.Where(o => o.DeleteMark == null && o.EnabledMark.Equals(1)).OrderBy(o => o.SortCode).ToListAsync();
            if (!isAdmin)
            {
                data = data.TreeChildNode(organizeId, t => t.Id, t => t.ParentId);
            }
            return data.Select(m => m.Id).ToArray();
        }

        /// <summary>
        /// 下属机构
        /// </summary>
        /// <param name="organizeId">机构ID</param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<string>> GetSubsidiary(string organizeId)
        {
            var data = await _organizeRepository.Where(o => o.DeleteMark == null && o.EnabledMark.Equals(1)).OrderBy(o => o.SortCode).ToListAsync();
            data = data.TreeChildNode(organizeId, t => t.Id, t => t.ParentId);
            return data.Select(m => m.Id).ToList();
        }

        /// <summary>
        /// 根据节点Id获取所有子节点Id集合，包含自己
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<string>> GetChildIdListWithSelfById(string id)
        {
            var childIdList = await _organizeRepository.Where(u => u.ParentId.Contains(id) && u.DeleteMark == null).Select(u => u.Id).ToListAsync();
            childIdList.Add(id);
            return childIdList;
        }

        /// <summary>
        /// 获取机构成员列表
        /// </summary>
        /// <param name="organizeId">机构ID</param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<OrganizeMemberListOutput>> GetOrganizeMemberList(string organizeId)
        {
            var output = new List<OrganizeMemberListOutput>();
            if (organizeId.Equals("0"))
            {
                var data = await _organizeRepository.Where(o => o.ParentId.Equals("-1") && o.DeleteMark == null && o.EnabledMark.Equals(1)).OrderBy(o => o.SortCode).ToListAsync();
                data.ForEach(o =>
                {
                    output.Add(new OrganizeMemberListOutput
                    {
                        id = o.Id,
                        fullName = o.FullName,
                        enabledMark = o.EnabledMark,
                        type = o.Category,
                        icon = "icon-ym icon-ym-tree-organization3",
                        hasChildren = true,
                        isLeaf = false
                    });
                });
            }
            else
            {
                var userList = await _userRepository.Where(u => u.OrganizeId.Equals(organizeId) && u.EnabledMark.Equals(1) && u.DeleteMark == null).OrderBy(o => o.SortCode).ToListAsync();
                userList.ForEach(u =>
                {
                    output.Add(new OrganizeMemberListOutput()
                    {
                        id = u.Id,
                        fullName = u.RealName + "/" + u.Account,
                        enabledMark = u.EnabledMark,
                        type = "user",
                        icon = "icon-ym icon-ym-tree-user2",
                        hasChildren = false,
                        isLeaf = true
                    });
                });
                var departmentList = await _organizeRepository.Where(o => o.ParentId.Equals(organizeId) && o.DeleteMark == null && o.EnabledMark.Equals(1)).OrderBy(o => o.SortCode).ToListAsync();
                departmentList.ForEach(o =>
                {
                    output.Add(new OrganizeMemberListOutput()
                    {
                        id = o.Id,
                        fullName = o.FullName,
                        enabledMark = o.EnabledMark,
                        type = o.Category,
                        icon = "icon-ym icon-ym-tree-department1",
                        hasChildren = true,
                        isLeaf = false
                    });
                });

            }
            return output;
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [NonAction]
        public async Task<OrganizeEntity> GetInfoById(string Id)
        {
            return await _organizeRepository.SingleAsync(p => p.Id == Id);
        }

        #endregion
    }
}
